﻿using Company.Config;
using Company.Hardware.Acs;
using Company.IO;
using Company.Share.Events;
using System.Collections.ObjectModel;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Threading;

namespace Company.Main.ViewModels
{
    public class DigitalOutputViewModel : BindableBase
    {
        #region 字段
        private DispatcherTimer UpDataOutputTimer = new DispatcherTimer();
        private ObservableCollection<EOUT> eOUTs;
        private bool isAcsConnected;
        private bool IsRunningUpData = false;

        public bool IsAcsConnected
        {
            get { return isAcsConnected; }
            set { isAcsConnected = value; RaisePropertyChanged(); }
        }

        #endregion
        #region 属性
        public ObservableCollection<EOUT> EOUTs
        {
            get { return eOUTs; }
            set { eOUTs = value; RaisePropertyChanged(); }
        }
        public AcsControllerProvider AcsControllerProvider { get; private set; }
        public DelegateCommand<object> WriteDigitalOutputToAcsCommand { get; }
        #endregion
        public DigitalOutputViewModel(AcsControllerProvider acsControllerProvider,
                                      ConfigProvider configProvider,
                                      IEventAggregator eventAggregator)
        {
            // 从Ioc中获取对象实例
            AcsControllerProvider = acsControllerProvider;
            EOUTs = configProvider.IoConfig.Output.EOUTs;
            WriteDigitalOutputToAcsCommand = new DelegateCommand<object>(WriteDigitalOutputToAcs);
            // 事件注册
            AcsControllerProvider.AcsController.AcsDisconnecting += () =>
            {
                //if (tokenSource == null) return;
                //// 线程取消
                //tokenSource.Cancel();
                UpDataOutputTimer.Stop();
                IsRunningUpData = false;
            };
            UpDataOutputTimer.Interval = TimeSpan.FromMilliseconds(50);
            UpDataOutputTimer.Tick += (s, e) => ReadDigitalInputCyclically();
            // 使用事件聚合器订阅
            eventAggregator.GetEvent<AcsControllerConnectedEvent>().Subscribe((obj) =>
            {
                IsAcsConnected = obj;
                if (IsAcsConnected)
                {
                    if (!IsRunningUpData)
                    {
                        //_GetDataFromAcsControllerTask = new Task(ReadDigitalInputCyclically, cancellationToken, TaskCreationOptions.LongRunning);//线程读取
                        //_GetDataFromAcsControllerTask.Start();
                        //IsRunningUpData = true;
                        //_GetDataFromAcsControllerTask.ContinueWith(t =>
                        //{
                        //    IsRunningUpData = false;
                        //});
                        UpDataOutputTimer.Start();
                        IsRunningUpData = true;
                    }
                }
            });
        }
        #region 线程读取
        /// <summary>
        /// 循环读取数字量输入
        /// </summary>
        private void ReadDigitalInputCyclically()
        {
            if (AcsControllerProvider.AcsController.IsConnected)
            {
                foreach (var item in EOUTs)
                {
                    ReadDigitalOutput(item.Variables);
                }
            }
        }
        /// <summary>
        /// 读取数字量输入
        /// </summary>
        /// <param name="digitalIOs"></param>
        private void ReadDigitalOutput(ObservableCollection<Variable> Variables)
        {
            if (!AcsControllerProvider.AcsController.IsConnected) return;
            foreach (Variable item in Variables)
            {
                var sResponse = AcsControllerProvider.AcsController.SendCommand("?" + item.Symbol);
                var sResult = Regex.Replace(sResponse, @"[^0-9]", "");
                if (sResult == "1")
                    item.Value = "TRUE";
                else
                    item.Value = "FALSE";
            }
        }
        /// <summary>
        /// 向Acs写入数字量输出
        /// </summary>
        /// <param name="obj"></param>
        private void WriteDigitalOutputToAcs(object obj)
        {
            if (!AcsControllerProvider.AcsController.IsConnected) return;
            Variable eout = (Variable)obj;
            if (eout.Value == "TRUE")
                AcsControllerProvider.AcsController.SendCommand(eout.Symbol + "=" + "0");
            else
                AcsControllerProvider.AcsController.SendCommand(eout.Symbol + "=" + "1");
        }
        #endregion
    }
}
